﻿/*****************************************************************
// Copyright (C) 2011-2099 ZdSoft Corporation
// All rights reserved.
// 
// Author:       wunaigong
// Create Date:  2011-07-20 22:15:47
// Usage: 试用次数
//
// RevisionHistory
// Date				Author				Description
*****************************************************************/

using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

//using System.Windows.Forms;

namespace Portal
{
    [Serializable]
    public class RsaClient
    {
        #region 变量

        //试用天数
        private const int DemoDays = 30;

        //试用次数
        private const int DemoTimes = 100;

        //公钥
        private readonly string _publicKey;

        //RSA实例
        private readonly RSACryptoServiceProvider _rsa;

        //软件中文名称
        private readonly string _softNameChn = "姿迪软件开发有限公司";

        //软件英文名称
        private readonly string _softNameEng = "ZiDiSoft";

        //加密Key
        private const string DefaultKey = "Wng912X/P8m=";

        //加密向量
        private const string DefalutIV = "o51xjm912cD=";

        //注册码
        private static string _registerKey = string.Empty;

        #endregion

        #region 构造函数

        public RsaClient()
        {
            _rsa = new RSACryptoServiceProvider();
            _publicKey = AppGlobals.GetTextFromResource("Portal.Resource", "PublicKey");
        }

        public RsaClient(string chn, string eng)
        {
            _rsa = new RSACryptoServiceProvider();
            _publicKey = AppGlobals.GetTextFromResource("Portal.Resource", "PublicKey");
            _softNameChn = chn;
            _softNameEng = eng;
        }

        #endregion


        /// <summary>
        /// 验证许可
        /// </summary>
        /// <returns></returns>
        public bool CheckLicneceKey()
        {
            try
            {
                var obj = XmlUtils.Deserialize(typeof (LicenceInfo),System.Web.HttpContext.Current.Server.MapPath("~/bin/Licence.xml"));
                if (obj == null)
                {
                    return false;
                }
                var lk = ((LicenceInfo) obj).LicenceKey;
                var rk = this.PrepareRegisterKey();
                this._rsa.FromXmlString(this._publicKey);
                var f = new RSAPKCS1SignatureDeformatter(this._rsa);
                f.SetHashAlgorithm("SHA1");
                byte[] key = Convert.FromBase64String(lk);
                byte[] name = new SHA1Managed().ComputeHash(Encoding.ASCII.GetBytes(rk));
                return f.VerifySignature(name, key);
            }
            catch (Exception)
            {
                return false;
            }
        }


        /// <summary>
        /// 验证许可
        /// </summary>
        /// <param name="licenceKey">许可证</param>
        /// <param name="registerKey">注册密钥</param>
        public bool CheckLicneceKey(string licenceKey, string registerKey)
        {
            try
            {
                _rsa.FromXmlString(_publicKey);
                var f = new RSAPKCS1SignatureDeformatter(this._rsa);

                //设置用于验证签名的哈希算法
                f.SetHashAlgorithm("SHA1");

                //Convert.ToBase64String();
                var key = Convert.FromBase64String(licenceKey);
                var name = new SHA1Managed().ComputeHash(Encoding.ASCII.GetBytes(registerKey));
                return f.VerifySignature(name, key);
            }
            catch (Exception)
            {
                return false;
            }
        }

        /// <summary>
        /// 验证许可
        /// </summary>
        /// <returns></returns>
        public SoftStateResult CheckSoftLicence()
        {
            return this.CheckSoftLicence(100);
        }

        /// <summary>
        /// 验证许可
        /// </summary>
        /// <param name="customDemoLimit">使用次数限制</param>
        /// <returns></returns>
        public SoftStateResult CheckSoftLicence(int customDemoLimit)
        {
            var r = new SoftStateResult();
            if (CheckLicneceKey())
            {
                r.SoftState = SoftState.Registered;
                r.Result = "(正式版)";
                return r;
            }
            return r;
            //return CheckTimesLimit();
        }


        /// <summary>
        /// Sha1加密
        /// </summary>
        /// <param name="source">明文</param>
        /// <returns>密文</returns>
        public string EncBySha1(string source)
        {
            new RSAPKCS1SignatureDeformatter(_rsa).SetHashAlgorithm("SHA1");
            try
            {
                var sha = new SHA1Managed();
                return Convert.ToBase64String(sha.ComputeHash(Encoding.ASCII.GetBytes(source)));
            }
            catch (Exception)
            {
                return string.Empty;
            }
        }

      
        /// <summary>
        /// 生成注册码
        /// </summary>
        /// <returns></returns>
        public string PrepareRegisterKey()
        {
            return PrepareRegisterKey(_softNameEng);
        }

        /// <summary>
        /// 生成注册码
        /// </summary>
        /// <param name="softname">软件名称</param>
        /// <returns>注册码</returns>
        public string PrepareRegisterKey(string softname)
        {
            if(string.IsNullOrEmpty(_registerKey))
            {
                _registerKey = EncBySha1(softname + "-" + new HardwareInfo().GetCpuID());
                return _registerKey;
            }
            var f = new RSAPKCS1SignatureFormatter(_rsa);

            //生成  软件名称+硬盘码
            var key = softname + "-" + new HardwareInfo().GetCpuID();
            f.SetHashAlgorithm("SHA1");
            return EncBySha1(key);
        }


        #region 验证试用(次数)

        //验证试用(次数)
        public SoftStateResult CheckTimesLimit()
        {
            var softStateResult = new SoftStateResult();

            //文件名称
            var fileName = Environment.SystemDirectory + @"\l" +
                           AppGlobals.BytesToString(Encoding.UTF8.GetBytes(this._softNameEng)).Substring(1, 6) + ".lrc";
            var mph = new PDSASymmetric(DefaultKey, DefalutIV);

            //实用次数
            int curDemoLimit;

            if (File.Exists(fileName))
            {
                //读取文件
                var demoTimesLimit = AppGlobals.ReadTextFromFile(fileName);

                //解密文件内容
                demoTimesLimit = mph.Decrypt(demoTimesLimit);

                //获取到时间和已使用次数
                var olds = demoTimesLimit.Substring(demoTimesLimit.IndexOf("{") - 1,
                                                    (demoTimesLimit.IndexOf("}") - demoTimesLimit.IndexOf("{")) + 2);

                //已使用次数加1
                curDemoLimit =
                    int.Parse(olds.Substring(olds.IndexOf("|") + 1, (olds.IndexOf("}") - olds.IndexOf("|")) - 1)) + 1;

                //新使用时间和使用次数
                var news = "{" + DateTime.Now.ToString() + "|" + curDemoLimit.ToString() + "}";

                //加密
                demoTimesLimit = mph.Encrypt(demoTimesLimit.Replace(olds, news));

                //重写到文件
                AppGlobals.WriteTextToFile(fileName, demoTimesLimit);
            }
            else
            {
                var demoTimesLimit = AppGlobals.GetTextFromResource("Portal.Resource", "DemoTimesLimit");
                var curDate = DateTime.Now;
                curDemoLimit = 1;
                demoTimesLimit = demoTimesLimit.Replace("{demo}",
                                                        "{" + curDate.ToString() + "|" + curDemoLimit.ToString() + "}");
                demoTimesLimit = mph.Encrypt(demoTimesLimit);
                AppGlobals.WriteTextToFile(fileName, demoTimesLimit);
            }

            var limit = DemoTimes - curDemoLimit;
            var limitString = "(还可试用" + limit.ToString() + "次,请与我们联系!)";
            if (limit > 0)
            {
                softStateResult.SoftState = SoftState.AllowDemo;
                if (limit < 15)
                {
                    softStateResult.Result = limitString;
                    return softStateResult;
                }
                softStateResult.Result = "(试用版)";
                return softStateResult;
            }
            //if (this.ShowRegisterForm() == DialogResult.Yes)
            //{
            //    softStateResult.SoftState = SoftState.Registered;
            //    softStateResult.Result = "(正式版)";
            //    return softStateResult;
            //}
            softStateResult.SoftState = SoftState.NotAllowDemo;
            softStateResult.Result = "(超过试用期限)";
            return softStateResult;
        }

        #endregion

        #region 验证试用(天数)

        //验证试用(天数)
        public SoftStateResult CheckDaysLimit()
        {
            var softStateResult = new SoftStateResult();

            //文件名称
            var fileName = Environment.SystemDirectory + @"\l" +
                           AppGlobals.BytesToString(Encoding.UTF8.GetBytes(this._softNameEng + "Days")).Substring(1, 6) +
                           ".lrc";
            var mph = new PDSASymmetric(DefaultKey, DefalutIV);

            //使用用天数
            int curDemoLimit = 0;

            //如果文件存在则读取，不存在则创建
            if (File.Exists(fileName))
            {
                //读取文件
                var demoTimesLimit = AppGlobals.ReadTextFromFile(fileName);

                //解密文件内容
                demoTimesLimit = mph.Decrypt(demoTimesLimit);

                //获取到时间和已使用次数
                var olds = demoTimesLimit.Substring(demoTimesLimit.IndexOf("{") - 1,
                                                    (demoTimesLimit.IndexOf("}") - demoTimesLimit.IndexOf("{")) + 2);

                var date = olds.Substring(2, 11);

                //按天计数，则以天作比较
                if (Convert.ToDateTime(date).Date != DateTime.Now.Date)
                {
                    //已使用次数加1
                    curDemoLimit =
                        int.Parse(olds.Substring(olds.IndexOf("|") + 1, (olds.IndexOf("}") - olds.IndexOf("|")) - 1)) + 1;
                    //新使用时间和使用次数
                    var news = "{" + DateTime.Now.ToString() + "|" + curDemoLimit.ToString() + "}";

                    //加密
                    demoTimesLimit = mph.Encrypt(demoTimesLimit.Replace(olds, news));

                    //重写到文件
                    AppGlobals.WriteTextToFile(fileName, demoTimesLimit);
                }


            }
            else
            {
                var demoTimesLimit = AppGlobals.GetTextFromResource("Portal.Resource", "DemoDaysLimit");
                var curDate = DateTime.Now;
                curDemoLimit = 1;
                demoTimesLimit = demoTimesLimit.Replace("{demo}",
                                                        "{" + curDate.ToString() + "|" + curDemoLimit.ToString() + "}");
                demoTimesLimit = mph.Encrypt(demoTimesLimit);
                AppGlobals.WriteTextToFile(fileName, demoTimesLimit);
            }
            int limit = DemoDays - curDemoLimit;
            var limitString = "(还可试用" + limit.ToString() + "天,请与我们联系!)";
            if (limit > 0)
            {
                softStateResult.SoftState = SoftState.AllowDemo;
                if (limit < 15)
                {
                    softStateResult.Result = limitString;
                    return softStateResult;
                }
                softStateResult.Result = "(试用版)";
                return softStateResult;
            }
            softStateResult.SoftState = SoftState.NotAllowDemo;
            softStateResult.Result = "(超过试用期限)";
            return softStateResult;
        }

        #endregion
    }
}